package org.utils.pool;

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.utils.common.InitException;
import org.utils.util.Configurable;
import org.utils.xml.XMLConfigurable;
import org.utils.xml.XMLDataNode;

/**
 * @author Manuel EVENO
 */
public class ResourceManager implements XMLConfigurable, Configurable
{
	protected static ResourceManager instance = null;
	/**
	 * Returns the instance.
	 * @return ResourceManager
	 */
	public static ResourceManager getInstance()
	{
		if (instance == null)
			instance = new ResourceManager();
		return instance;
	}
	
	public static final String DEFAULT_KEY = "DefaultResourceManager";

	protected static Hashtable managers = null;
	
	protected LinkedList resources = null;
	/**
	 * Constructor for ResourceManager.
	 */
	public ResourceManager()
	{
		this(new LinkedList());
	}
	/**
	 * Constructor for ResourceManager.
	 */
	public ResourceManager(LinkedList items)
	{
		super();
		resources = items;
	}
	/**
	 * @see org.utils.xml.XMLConfigurable#configure(XMLDataNode)
	 */
	public void configure(XMLDataNode config) throws InitException
	{
	}
	/**
	 * @see org.utils.util.Configurable#configure(Properties)
	 */
	public void configure(Properties properties) throws InitException
	{
	}
	/**
	 * Initialize the manager with the given resource objects
	 */
/*	protected void init(LinkedList items)
	{
		
	}*/
	/**
	 * Returns a free resource
	 * @return Object
	 */
	public synchronized Object getResource() throws ResourceException
	{
		try
		{
			Object resource = null;
			while (resources.size() == 0)
			{
				Logger.getLogger(this.getClass()).debug("Is Waiting for Resource");
				wait();
			}
			if (resources.size() == 0)
				return null;
      			Logger.getLogger(this.getClass()).info("Is Getting Resource");
			resource = resources.removeFirst();//get(0);
			//resources.remove(0);
			return resource;
		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			throw new ResourceException("No resource available", e);
		}
		catch (NullPointerException e)
		{
			throw new ResourceException("No resource available", e);
		}
		catch (Exception e)
		{
			throw new ResourceException("Can't get resource", e);
		}
	}
	/**
	 * Release a resource after use.
	 */
	public synchronized void releaseResource(Object resource)
	{
		Logger.getLogger(this.getClass()).debug("Is Adding Object in pool");
		resources.addLast(resource);
	}
	
	/**
	 * Return the number of resource available
	 * @return int
	 */
	public synchronized int getAvailableResourceCount()
	{
		//Logger.getLogger(this.getClass()).debug("Current Resource available: "+resources.size());
		return resources.size();
	}
}
